#!/usr/bin/env python
#

import logging
import urllib
import time
import models
import datetime
import utils
import simplejson
import ytapi_helper
import httplib2

from oauth2client.appengine import CredentialsModel, OAuth2Decorator, \
    StorageByKeyName


class YTPlaylistUpdater(ytapi_helper.YTApiHelper):
  """Class that will sync curated videos into YT playlists.

  This cannot run as a mapreduce because writes to playlists incur 2x QPS
  compared to read QPS.

  This should only run once per 2hrs to ensure the YT api is returning the
  latest data.
  """
  UPDATE_DELAY = 1 # delay between playlist update

  def __init__(self, userid):
    self.userid = userid
    self.owner_credentials = StorageByKeyName(
        CredentialsModel, userid, 'credentials').get()
    logging.info(self.owner_credentials)
    try:
      self.owner_credentials._refresh(httplib2.Http().request)
    except Exception, e:
      logging.info(e)

    #yt_helper = ytapi_helper.YTApiHelper(owner_credentials.access_token)
    ytapi_helper.YTApiHelper.__init__(self, self.owner_credentials.access_token)


  def _BuildPlaylistVideoGroups(self):
    """Build a dictionary for each playlist with alist of all videoids.

    Args:
      sql_rows: The table rows from curated_videos table.

    Returns:
      dictionary containing {playlistid:[videoid1, videoid2]}
    """
    self.playlists = models.WhiteLabelPlaylistBuckets.all().filter(
        'is_available', False).fetch(200)
    playlist_videos = {}
    for yt_pl in self.playlists:
      tagged_yt_pl = models.Tags.all().filter(
          'playlistid', yt_pl.playlistid).get()
      playlist_videos.update({yt_pl.playlistid: tagged_yt_pl.videoidlist})

    return playlist_videos

  def RunPlaylistSync(self):
    """Sync curated videos to YouTube.

    Each playlist sync will take ~3mins. Ie 200videos, 1 sec per video
    200 videos X 250 playlists = 10 hours
    Task queues will only be able to complete 3 playlists sync.
    This needs to run as backends.
    """
    
    #yt_helper = ytapi_helper.YTApiHelper(owner_credentials.access_token)
    curated_videos_dict = self._BuildPlaylistVideoGroups()
    logging.info('curated_videos_dict :%s' % curated_videos_dict)

    youtube_playlist_videos = {}
    for playlistid in curated_videos_dict.keys():
      if not youtube_playlist_videos.has_key(playlistid):
        youtube_playlist_videos[playlistid] = self.GetPlaylistVideos(
            playlistid)
      logging.info('youtube_playlist_videos- %s', youtube_playlist_videos)
      videos_to_delete = set(
          youtube_playlist_videos[playlistid].keys()).difference(
              curated_videos_dict[playlistid])

      videos_to_add = set(curated_videos_dict[playlistid]).difference(
          youtube_playlist_videos[playlistid].keys())

      for videoid in videos_to_delete:
        time.sleep(self.UPDATE_DELAY)
        try:
          self.DeleteVideoFromPlaylist(
              playlistid, youtube_playlist_videos[playlistid][videoid])
          logging.info(
              'delete success playlistid:%s - %s', playlistid, videoid)
        except Exception, e:

          logging.info(e)
          logging.info(
              'delete failed playlistid:%s - %s', playlistid, videoid)

      for videoid in videos_to_add:
        time.sleep(self.UPDATE_DELAY)
        try:
          self.AddVideoToPlaylist(playlistid, videoid)
          logging.info(
              'adding success playlistid:%s - %s', playlistid, videoid)
        except Exception, e:
          # remove video from list if failed, perhaps remove from db entirely
          logging.info(e)
          message = 'failed to add %s into playlistid:%s - %s' % (videoid, playlistid, e)
          logging.info(message)
      #TODO:update synced time


def main():
  ONE_HR = 3600
  while True:
    logging.info('running backend sync')
    now = datetime.datetime.now()
    user = models.OAuthUser.all().get()
    if user:
      yt_updater = YTPlaylistUpdater(user.userid)
      yt_updater.RunPlaylistSync()
    time.sleep(ONE_HR * 2)


if __name__ == '__main__':
  main()
